﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bettzueche.RLLibrary.Types;

namespace Bettzueche.RLLibrary.Functions {
    /// <summary>
    /// Die deterministische Strategie Pi ist ein Spezialfall der stochastischen.<para>In jedem Zustand wird genau eine
    /// Aktion möglich. die Wahrscheinlichkeit für diese eine Aktion ist also 1, während sie für alle anderen Aktionen
    /// der Aktionsmenge 0 ist.</para><para>
    /// Diese Klasse unterstützt zusätlich eine Indizierung über den Zustand: <code>action = detPolicy[state]</code>. Es wird
    /// empfohlen, nur mit diesem und nicht mit dem geerbten Index zu arbeiten.</para>
    /// </summary>
    public class DeterministicPolicy : StochasticPolicy {

        Dictionary<IState, IAction> pVals;

        /// <summary>
        /// Gets or sets the <see cref="Bettzueche.RLLibrary.Types.IAction"/> with the specified state.<para>
        /// Returns null, if no action was found corresponding to specified state</para>
        /// </summary>
        public virtual IAction this[IState state] {
            get {
                IAction result;
                try {
                    result = pVals[state];
                }
                catch (KeyNotFoundException) {
                    return null;
                }
                return result;
            }
            set { 
                pVals[state] = value;
            }
        }

        /// <summary>
        /// ...
        /// pol[state, action] = 1 oder mehr: a = pol[state] liefert 'action'.
        /// pol[state, action] = 0 oder weniger: a = pol[state] liefert null (zuvor vorhandener Wert wird entfernt!)
        /// pol[state, action] = 0 &lt; d &lt; 1 : wird ignoriert.
        /// </summary>
        public override double this[IState state, IAction action] {
            get {
                if (pVals.Contains(new KeyValuePair<IState, IAction>(state, action)))
                    return 1.0;
                else
                    return 0.0;
            }
            set {
                if (value >= 1.0)
                    pVals[state] = action;
                if (value <= 0.0)
                    pVals.Remove(state);
                // else ignore.
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DeterministicPolicy"/> class.
        /// </summary>
        public DeterministicPolicy() {
            pVals = new Dictionary<IState, IAction>();
        }
    }
}
